import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_demo/demo/route/detail.dart';

void main() => runApp(MaterialApp(home: MyApp()));

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Animation")),
      body: MyBody(),
      floatingActionButton: FloatingActionButton(
        child: Text(
          "自定义动画弹窗",
          style: TextStyle(color: Colors.black),
        ),
        onPressed: () {
          Navigator.of(context).push(PageRouteBuilder(
            transitionDuration: Duration(seconds: 3),
            pageBuilder: (context, animation, secondaryAnimation) {
              return FadeTransition(
                opacity: animation,
                child: DetailPage(counter: 1),
              );
            },
          ));
        },
      ),
    );
  }
}

class MyBody extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: const [
        Heartbeat(),
        Divider(thickness: 1),

        /// 使用 AnimationWidget 优化，不需要每次都重新执行 build 方法
        /// 缺点：1 必须要使用一个新的类来继承 AnimationWidget
        ///      2 如果该类有子类，那么子类依然会执行 build 方法
        HorizontalMove(),
        Divider(thickness: 1),

        /// 使用 AnimationBuilder 优化，不会重新执行子类的 build
        ExtendWidget(),
        Divider(thickness: 1),

        /// 交织动画
        ComplexShape()
      ],
    );
  }
}

class Heartbeat extends StatefulWidget {
  const Heartbeat({Key? key}) : super(key: key);

  @override
  State<Heartbeat> createState() => _HeartbeatState();
}

class _HeartbeatState extends State<Heartbeat> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  bool _flag = false;

  @override
  void initState() {
    super.initState();

    /// 1. 创建 AnimationController
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 2));

    /// 2. 设置速度
    _animation = CurvedAnimation(curve: Curves.easeOutBack, parent: _controller);

    /// 3. Tween 设置尺寸
    _animation = Tween<double>(begin: 30.0, end: 50.0).animate(_animation);

    /// 监听，会重新构建整个 build 方法
    _controller.addListener(() {
      setState(() {});
    });

    _controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _controller.forward();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(height: 10),
        Row(
          children: [
            Switch(
                value: _flag,
                onChanged: (v) {
                  setState(() {
                    _flag = v;
                  });
                  if (v) {
                    if (_animation.status == AnimationStatus.forward ||
                        _animation.status == AnimationStatus.dismissed) {
                      _controller.forward();
                    } else {
                      _controller.reverse();
                    }
                  } else {
                    _controller.stop();
                  }
                }),
            Expanded(child: Icon(Icons.favorite, color: Colors.red, size: _animation.value)),
          ],
        ),
      ],
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

class HorizontalMove extends StatefulWidget {
  const HorizontalMove({Key? key}) : super(key: key);

  @override
  State<HorizontalMove> createState() => _HorizontalMoveState();
}

class _HorizontalMoveState extends State<HorizontalMove> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  bool _flag = false;

  @override
  void initState() {
    super.initState();

    /// 1. 创建 AnimationController
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 1));

    /// 2. 设置速度
    _animation = CurvedAnimation(curve: Curves.linear, parent: _controller);

    /// 3. Tween 设置尺寸
    _animation = Tween<double>(begin: 10, end: 200).animate(_animation);

    _controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _controller.forward();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      SizedBox(height: 10),
      Row(
        children: [
          Switch(
              value: _flag,
              onChanged: (v) {
                setState(() {
                  _flag = v;
                });
                if (v) {
                  if (_animation.status == AnimationStatus.forward ||
                      _animation.status == AnimationStatus.dismissed) {
                    _controller.forward();
                  } else {
                    _controller.reverse();
                  }
                } else {
                  _controller.stop();
                }
              }),
          Expanded(child: HorizontalMoveWidget(_animation)),
        ],
      ),
    ]);
  }
}

class HorizontalMoveWidget extends AnimatedWidget {
  HorizontalMoveWidget(Listenable listenable) : super(listenable: listenable);

  @override
  Widget build(BuildContext context) {
    return Stack(children: [
      SizedBox(height: 50, width: 200),
      Positioned(
          left: (listenable as Animation).value,
          child: Container(height: 40, width: 40, color: Colors.black))
    ]);
  }
}

class ExtendWidget extends StatefulWidget {
  const ExtendWidget({Key? key}) : super(key: key);

  @override
  State<ExtendWidget> createState() => _ExtendWidgetState();
}

class _ExtendWidgetState extends State<ExtendWidget> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  bool _flag = false;

  @override
  void initState() {
    super.initState();

    /// 1. 创建 AnimationController
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 2));

    /// 3. Tween 设置尺寸
    _animation = Tween<double>(begin: 50, end: 150)
        .animate(CurvedAnimation(curve: Curves.linearToEaseOut, parent: _controller));

    /// 监听，会重新构建整个 build 方法
    _controller.addListener(() {
      setState(() {});
    });

    _controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        _controller.forward();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(height: 10),
        Row(
          children: [
            Switch(
                value: _flag,
                onChanged: (v) {
                  setState(() {
                    _flag = v;
                  });
                  if (v) {
                    if (_animation.status == AnimationStatus.forward ||
                        _animation.status == AnimationStatus.dismissed) {
                      _controller.forward();
                    } else {
                      _controller.reverse();
                    }
                  } else {
                    _controller.stop();
                  }
                }),
            Expanded(
              child: Container(
                height: 50,
                width: 200,
                child: UnconstrainedBox(
                  child: AnimatedBuilder(
                    animation: _controller,
                    builder: (BuildContext context, Widget? child) {
                      return Container(
                        alignment: Alignment.bottomCenter,
                        height: 40,
                        width: _animation.value,
                        color: Colors.blue,
                      );
                    },
                  ),
                ),
              ),
            ),
          ],
        ),
      ],
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

/// 执行 3 个动画
/// 1. 大小变化
/// 2. 颜色变化
/// 3. 旋转
class ComplexShape extends StatefulWidget {
  const ComplexShape({Key? key}) : super(key: key);

  @override
  State<ComplexShape> createState() => _ComplexShapeState();
}

class _ComplexShapeState extends State<ComplexShape> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _sizeAnmt;
  late Animation<double> _transformAnmt;
  late Animation<Color?> _colorAnmt;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 3));
    Animation<double> curved = CurvedAnimation(parent: _controller, curve: Curves.bounceInOut);
    _sizeAnmt = Tween<double>(begin: 70.0, end: 200.0).animate(curved);
    _transformAnmt = Tween<double>(begin: 0, end: pi * 2).animate(curved);
    _colorAnmt = ColorTween(begin: Colors.deepOrange, end: Colors.cyanAccent).animate(curved);

    _controller.forward();
    _controller.addStatusListener((status) {
      if (status == AnimationStatus.dismissed) {
        _controller.forward();
      } else if (status == AnimationStatus.completed) {
        _controller.reverse();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Center(
        child: AnimatedBuilder(
          builder: (BuildContext context, Widget? child) {
            return Transform(
              transform: Matrix4.rotationZ(_transformAnmt.value),
              alignment: Alignment.center,
              child: Container(
                height: _sizeAnmt.value,
                width: _sizeAnmt.value,
                color: _colorAnmt.value,
              ),
            );
          },
          animation: _controller,
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}
